package com.zf.yichat.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.ServiceException;
import com.github.pagehelper.PageHelper;
import com.zf.yichat.dto.*;
import com.zf.yichat.dto.im.UserSearchDto;
import com.zf.yichat.mapper.*;
import com.zf.yichat.model.*;
import com.zf.yichat.service.*;
import com.zf.yichat.service.config.ConfigSet;
import com.zf.yichat.service.config.RedisService;
import com.zf.yichat.service.config.RongCloudApplication;
import com.zf.yichat.utils.MobileSplit;
import com.zf.yichat.utils.ServiceUtils;
import com.zf.yichat.utils.YiChatMsgCode;
import com.zf.yichat.utils.common.*;
import com.zf.yichat.utils.response.FsPage;
import com.zf.yichat.utils.response.FsResponse;
import com.zf.yichat.utils.response.FsResponseGen;
import com.zf.yichat.vo.*;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.hibernate.validator.internal.util.Contracts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 一句话描述功能
 *
 * @author fengsong
 * @date create in 15:50 2019/5/28 2019
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    private UserInviteMapper userInviteMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private PacketSaleViewMapper packetSaleViewMapper;

    @Resource
    private UserDeviceMapper userDeviceMapper;

    @Resource
    private ImApiService imApiService;

    @Resource
    private UserImMapper userImMapper;

    @Resource
    private SecurityService securityService;

    @Resource
    private ThirdLoginMapper thirdLoginMapper;

    @Autowired
    private BalanceService balanceService;

    @Resource
    private UserBankMapper userBankMapper;

    @Resource
    private UserBankXsMapper userBankXsMapper;

    @Autowired
    private RedisService redisService;

    @Resource
    private UserSignMapper userSignMapper;

    @Resource
    private UserBalanceMapper userBalanceMapper;

    @Resource
    private UserBalanceDetailMapper userBalanceDetailMapper;

    @Resource
    private FriendMapper friendMapper;

    @Resource
    private FriendApplyMapper friendApplyMapper;

    @Resource
    private UserWithdrawMapper userWithdrawMapper;

    @Autowired
    private ConfigSet configSet;

    @Resource
    private UserIpMapper userIpMapper;

    @Resource
    private WxUserMapper wxUserMapper;

    @Autowired
    private PushService pushService;

    @Autowired
    private UserIntegralDetailMapper userIntegralDetailMapper;

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private MemberLevelMapper memberLevelMapper;

    @Autowired
    private MemberLevelPrivilegeMapper memberLevelPrivilegeMapper;

    @Autowired
    private UserPrintTreeTaskMapper userPrintTreeTaskMapper;

    @Autowired
    private PlantTreeService plantTreeService;

    @Value("${st.im_uri}")
    private String imUri;

    // 注入配置文件中的融云API配置
    @Value("${rongcloud.key}")
    private String appKey;

    @Value("${rongcloud.secret}")
    private String appSecret;

    @Autowired
    private RongCloudApplication rongCloudApplication;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserIm add(User user) {

        MobileSplit split = ServiceUtils.splitMobile(user.getMobile());
        user.setAreaCode(split.getAreaCode());
        user.setMobile(StringUtils.isBlank(split.getMobile()) ? null : split.getMobile());
        // 使用MD5加密
        user.setPassword(MD5Util.string2MD5(user.getPassword()));
        //获取盐值  验证token

        // user.setSalt(ServiceUtils.generateSalt());

        //填充一个默认头像
        if (Objects.isNull(user.getAvatar())) {
            user.setAvatar(sysDictService.selectOne(DictKey.user_default_avatar).getValue());

        }

        //不设置默认有建群权限
        user.setCreateGroupAuth(Optional.ofNullable(configSet.getCreateGroupAuth()).orElse(1));
        user.setCtime(new Date());
        user.setStatus(FsConst.Status.EFFECT);
        if (configSet.isMobileAppIdStatus()) {
            user.setAppid(user.getMobile());
            user.setMobile(null);
        }

        user.setIntegral(0);
        user.setRealStatus(0);
        userMapper.insertUseGeneratedKeys(user);


//        User encryptionUser = new User();
//        encryptionUser.setId(user.getId());
//        // 使用MD5加密密码
//        encryptionUser.setPassword(MD5Util.string2MD5(user.getPassword()));
//        // 更新用户
//        userMapper.updateByPrimaryKey(encryptionUser);

        Contracts.assertTrue(Objects.nonNull(user.getId()), YiChatMsgCode.REGISTER_FAIL.msg());
        String ucode=createShareCode();

        Example example=new Example(User.class);
        example.createCriteria().andEqualTo("ucode",ucode);

        List<User> userCheck=userMapper.selectByExample(example);
        while (userCheck!=null&&userCheck.size()!=0){
            ucode=createShareCode();
        }
        //生成系统6位唯一码
        user.setUcode(ucode);
        try {
            String token = securityService.token(user.getSalt(), user.getId());
            user.setToken(token);
            userMapper.updateByPrimaryKeySelective(user);
        } catch (Exception e) {
            e.printStackTrace();
        }


        //        //创建IM账号 im密码随机6位数字
        //        String accountId = String.valueOf(user.getId());
        //        String imPassword = GeneralUtils.randomNum(6);
        //
        //        ImCommand res = imApiService.create(accountId, imPassword);
        //
        //        //极光注册
        //        pushService.createUser(accountId, imPassword);
        //
        //        Contracts.assertTrue(Objects.nonNull(res), YiChatMsgCode.REGISTER_FAIL.msg());
        //
        UserIm userIm = new UserIm();
        //        userIm.setImPassword(imPassword);
        //        userIm.setUserId(user.getId());
        //        userImMapper.insertSelective(userIm);

        //创建余额账号
        balanceService.create(user.getId());

        return userIm;
    }

    /**
     * 生成邀请码
     *
     * @return
     */
    private static String createShareCode() {
        int maxNum = 36;
        int i;
        int count = 0;
        char[] str = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
                'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
                'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
        StringBuffer code = new StringBuffer("");
        Random r = new Random();
        while (count < 6) {
            i = Math.abs(r.nextInt(maxNum));
            if (i >= 0 && i < str.length) {
                code.append(str[i]);
                count++;
            }
        }
        return code.toString();
    }


    @Override
    public void deleteUser(Long userId) {
        userMapper.deleteByPrimaryKey(userId);


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addThird(String nick, String avatar, String openId, String unionId, ThirdType thirdType) {


        //注册账号
        User add = new User();
        add.setNick(GeneralUtils.removeAllEmojis(nick));
        add.setAvatar(avatar);
        String imPassword = add(add).getImPassword();

        //第三方账号信息保存
        ThirdLogin thirdLogin = new ThirdLogin();
        thirdLogin.setType(thirdType.getVal());
        thirdLogin.setUniqueCode(openId);
        thirdLogin.setUnionId(unionId);
        thirdLogin.setUserid(add.getId());
        thirdLoginMapper.insertSelective(thirdLogin);

        return imPassword;
    }

    @Override
    public User selectByMobile(String mobile) {
        User query = new User();
        if (configSet.isMobileAppIdStatus()) {
            query.setMobile(mobile);
        } else {
            MobileSplit split = ServiceUtils.splitMobile(mobile);
            query.setMobile(split.getMobile());
        }
        return userMapper.selectOne(query);
    }

    @Override
    public User selectByAlipayAccount(String alipayAccount) {
        User query = new User();
        query.setAlipayAccount(alipayAccount);
        return userMapper.selectOne(query);
    }

    @Override
    public List<User> selectByIdNumber(String idNumber) {
        Example example = new Example(User.class);
        example.createCriteria().andEqualTo("idNumber", idNumber);
        return userMapper.selectByExample(example);
    }

    @Override
    public List<UserDevice> selectDeviceByUserId(Long userId) {
        Example select = new Example(UserDevice.class);
        select.createCriteria().andEqualTo("userId", userId);
        return userDeviceMapper.selectByExample(select);
    }

    @Override
    public UserDevice selectDevice(Long id, String deviceId) {
        Example select = new Example(UserDevice.class);
        select.createCriteria().andEqualTo("userId", id).andEqualTo("deviceId", deviceId);
        return userDeviceMapper.selectOneByExample(select);
    }

    @Override
    public void update(User user) {
        userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public void updateNull(User user) {
        // 更新用户密码
        userMapper.updateByPrimaryKey(user);
    }

    @Override
    public UserIm selectIm(Long id) {
        Example example = new Example(UserIm.class);
        example.createCriteria().andEqualTo("userId", id);
        return userImMapper.selectOneByExample(example);
    }

    @Override
    public void updateDevice(Long id, String deviceId) {
        if (StringUtils.isBlank(deviceId)) {
            return;
        }
        userDeviceMapper.updateInsert(id, deviceId);
    }

    @Override
    public User selectById(Long userId) {

        return Optional.ofNullable(userMapper.selectByPrimaryKey(userId)).orElse(new User());

    }

    @Override
    public boolean isMember(Long userId) {

        User user = userMapper.queryUserByParam("", userId);
        if (null != user && user.getLevel() == User.LEVEL_MEMBER) {
            return true;
        }
        return false;
    }

    @Override
    public List<User> searchByMobileOrAppId(String content) {
        Example select = new Example(User.class);
        select.createCriteria().andEqualTo("status", UserStatusEnum.OPEN.getVal());

        //通过配置
        Example.Criteria other = select.createCriteria();
        other.andEqualTo("mobile", content);
        //是否开启应用ID搜索
        if (!configSet.getSearch().isCloseAppId()) {
            other.orEqualTo("appid", content);
        }
        select.and(other);
        return userMapper.selectByExample(select);
    }

    @Override
    public User selectByThirdAccount(String openId, String unionId) {
        Example example = new Example(ThirdLogin.class);
        example.createCriteria().andEqualTo(FsConst.SqlColumn.STATUS, FsConst.Status.EFFECT).andEqualTo("unionId", unionId);
        ThirdLogin thirdLogin = thirdLoginMapper.selectOneByExample(example);
        User user = null;
        if (Objects.nonNull(thirdLogin)) {
            user = selectById(thirdLogin.getUserid());
            //            //更新下unionId
            //            if (Objects.nonNull(unionId)) {
            //                thirdLogin.setUnionId(unionId);
            //                thirdLoginMapper.updateByPrimaryKeySelective(thirdLogin);
            //            }
        }
        if (Objects.isNull(user)) {
            Example example1 = new Example(ThirdLogin.class);
            example1.createCriteria().andEqualTo(FsConst.SqlColumn.STATUS, FsConst.Status.EFFECT).andEqualTo("uniqueCode", openId);
            ThirdLogin thirdLogin1 = thirdLoginMapper.selectOneByExample(example1);
            if (Objects.nonNull(thirdLogin1)) {
                user = selectById(thirdLogin1.getUserid());
            }
        }
        return user;
    }

    @Override
    public User selectByUnionId(String unionId) {
        Example example = new Example(ThirdLogin.class);
        example.createCriteria().andEqualTo(FsConst.SqlColumn.STATUS, FsConst.Status.EFFECT).andEqualTo("unionId", unionId);
        ThirdLogin thirdLogin = thirdLoginMapper.selectOneByExample(example);
        User user = null;
        if (Objects.nonNull(thirdLogin)) {
            user = selectById(thirdLogin.getUserid());
        }
        return user;
    }

    @Override
    public List<User> selectList(List<Long> idList) {
        Example example = new Example(User.class);
        example.createCriteria().andIn("id", idList);

        return userMapper.selectByExample(example);
    }

    @Override
    public FsResponse selectIndexList(FsPage page, String nick, Integer status, String mobile, String ucode) {

        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        /*if(){

        }*/
        example.setOrderByClause(" ctime desc");
        PageHelper.startPage(page.getPageNo(), page.getPageNo());
        return DtoChangeUtils.getPageList(userMapper.selectByExample(example), v -> v);
    }


    @Override
    public void adBankCard(UserBank userBank) {
        userBankMapper.insertSelective(userBank);
    }

    @Override
    public List<UserBank> selectBankList(Long userId) {
        Example example = new Example(UserBank.class);
        example.createCriteria().andEqualTo("status", 0).andEqualTo("userId", userId).andIsNotNull("hjbindcardno");
        example.setOrderByClause(" id");
        return userBankMapper.selectByExample(example);
    }

    @Override
    public List<UserBankXs> selectBankList2(Long userId) {
        Example example = new Example(UserBankXs.class);
        example.createCriteria().andEqualTo("status", 0).andEqualTo("userId", userId).andIsNotNull("xsbindcardagrno");
        example.setOrderByClause(" id");
        return userBankXsMapper.selectByExample(example);
    }

    @Override
    public void deleteBank(Integer bankId) {
        UserBank bank = new UserBank();
        bank.setId(bankId);
        bank.setStatus(1);
        userBankMapper.updateByPrimaryKeySelective(bank);
    }

    @Override
    public void deleteBank2(Integer bankId) {
        UserBankXs bank = new UserBankXs();
        bank.setId(bankId);
        bank.setStatus(1);
        userBankXsMapper.updateByPrimaryKeySelective(bank);
    }

    @Override
    public User selectByAppId(String mobile) {
        User query = new User();
        query.setAppid(mobile);
        return userMapper.selectOne(query);
    }


    private static String user_time_pre = "timestamp_";

    @Override
    @Async
    public void updateTimestamp(Long userId, Long time) {
        User query = new User();
        query.setId(userId);
        query.setTimestamp(time);
        userMapper.updateByPrimaryKeySelective(query);
        redisService.setVal(user_time_pre + userId, String.valueOf(time));
    }

    @Override
    public Long getTimestamp(Long userId) {
        String time = redisService.getVal(user_time_pre + userId);
        if (StringUtils.isNotBlank(time)) {
            return org.apache.commons.lang3.math.NumberUtils.toLong(time);
        } else {
            return Optional.ofNullable(selectById(userId).getTimestamp()).orElse(0L);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void crashUser(List<Long> userIds) {
        if (GeneralUtils.isNullOrEmpty(userIds)) {
            return;
        }
        userIds.forEach(v -> {
            User u = selectById(v);
            if (Objects.nonNull(u)) {
                //删除用户主体
                userMapper.deleteByPrimaryKey(v);
                //删除用户设备
                Example deviceDel = new Example(UserDevice.class);
                deviceDel.createCriteria().andEqualTo("userId", v);
                userDeviceMapper.deleteByExample(deviceDel);
                //删除余额信息
                Example balanceDel = new Example(UserBalance.class);
                balanceDel.createCriteria().andEqualTo("userId", v);
                userBalanceMapper.deleteByExample(balanceDel);
                //删除余额详细信息
                Example balanceDetailDel = new Example(UserBalanceDetail.class);
                balanceDetailDel.createCriteria().andEqualTo("userId", v);
                userBalanceDetailMapper.deleteByExample(balanceDetailDel);
                //删除银行信息
                Example bankDel = new Example(UserBank.class);
                bankDel.createCriteria().andEqualTo("userId", v);
                userBankMapper.deleteByExample(bankDel);

                //删除提现信息
                Example withDel = new Example(UserWithdraw.class);
                withDel.createCriteria().andEqualTo("userId", v);
                userWithdrawMapper.deleteByExample(withDel);

                //删除im账号信息
                Example imDel = new Example(UserIm.class);
                imDel.createCriteria().andEqualTo("userId", v);
                userImMapper.deleteByExample(imDel);

                //删除用户好友
                Example example = new Example(Friend.class);
                example.createCriteria().andEqualTo("userId", v);
                example.or(example.createCriteria().andEqualTo("friendId", v));
                friendMapper.deleteByExample(example);

                //删除好友申请
                Example appDel = new Example(FriendApply.class);
                appDel.createCriteria().andEqualTo("userId", v);
                appDel.or(appDel.createCriteria().andEqualTo("friendId", v));
                friendApplyMapper.deleteByExample(appDel);

                //删除第三方登陆
                Example tDel = new Example(ThirdLogin.class);
                tDel.createCriteria().andEqualTo("userid", v);
                thirdLoginMapper.deleteByExample(tDel);


            }
        });

        //im服务删除
        imApiService.deleteUser(userIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse recordSign(Long userId, boolean isSign) {

        UserSignDto dto = new UserSignDto();

//        BigDecimal score = new BigDecimal(Optional.ofNullable(redisService.getVal(DictKey.user_sign_get.name())).orElse("0"));
//        if (score.compareTo(BigDecimal.ZERO) == 0) {
//            SysDict sysDict = sysDictService.selectOne(DictKey.user_sign_get);
//            Contracts.assertNotNull(sysDict, YiChatMsgCode.USER_SIGN_FAIL.msg());
//            score = new BigDecimal(sysDict.getValue());
//        }
        BigDecimal score = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_get)).map(SysDict::getValue).orElse("2"));

        Calendar calendar = Calendar.getInstance();
        String todayDate = DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd");

        // 查询用户今日是否已签到
        Example exampleOne = new Example(UserSign.class);
        exampleOne.createCriteria().andEqualTo("signDate", todayDate).andEqualTo("userId", userId);
        UserSign userSign = userSignMapper.selectOneByExample(exampleOne);

        if (null != userSign) {
            dto.setSignState(UserSignDto.SIGN_STATE_REPEAT);
        }
        else {
            dto.setSignState(UserSignDto.SIGN_STATE_SUCCESS);
        }


        boolean isLastDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) == 1;
        List<String> weekDays = new ArrayList<>();

        boolean isHasGet = false;
        if (isSign) {


            Example ex = new Example(UserSign.class);
            ex.createCriteria().andEqualTo("userId", userId).andEqualTo("signDate", todayDate);
            if (Objects.isNull(userSignMapper.selectOneByExample(ex))) {
                //获取每天签到的值
                UserSign sign = new UserSign();
                sign.setSignDate(new Date());
                sign.setScore(score);
                sign.setUserId(userId);
                sign.setCtime(new Date());
                userSignMapper.insertUseGeneratedKeys(sign);

                //添加入账记录
                balanceService.update(userId, BalanceType.SIGN, score, sign.getId().longValue(), "签到获取");
            } else {
                isHasGet = true;
            }


        }


        //获取一周签到情况
        //重置日期为这周的第一天
        int d = calendar.get(Calendar.DAY_OF_WEEK);
        calendar.add(Calendar.DAY_OF_YEAR, d == 1 ? -6 : (2 - d));

        weekDays.add(DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd"));
        for (int i = 1; i < 7; i++) {
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            weekDays.add(DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd"));
        }

        //查询
        Example example = new Example(UserSign.class);
        example.createCriteria().andIn("signDate", weekDays).andEqualTo("userId", userId);

        List<UserSign> list = userSignMapper.selectByExample(example);

        //判断是否符合一周奖励
        //当前是否一周的最后一天
        //判断是否七天都签到
//        BigDecimal weekScore = new BigDecimal(Optional.ofNullable(redisService.getVal(DictKey.user_sign_continue_get.name())).orElse("0"));
//        if (weekScore.compareTo(BigDecimal.ZERO) == 0) {
//            SysDict sysDict = sysDictService.selectOne(DictKey.user_sign_continue_get);
//            Contracts.assertNotNull(sysDict, YiChatMsgCode.USER_SIGN_FAIL.msg());
//            weekScore = new BigDecimal(sysDict.getValue());
//        }
        BigDecimal weekScore = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_continue_get)).map(SysDict::getValue).orElse("0"));

        if (isLastDayOfWeek && list.size() == 7 && isSign && !isHasGet) {


            balanceService.update(userId, BalanceType.SIGN, weekScore, null, "签到一周获取");
        }

        // 查询用户近一个月的签到情况
        List<UserSign> listMonth = userSignMapper.selectUserSignMonth(userId);
        // 计算连续签到的天数
        int consecutiveDays = calculateConsecutiveDays(listMonth);
        // 获取当前月份的天数
//        int daysInMonth = calendar.getActualMaximum (Calendar.DAY_OF_MONTH);
        int daysInMonth = 30;
        // 判断是否是当月的最后一天
        boolean isLastDayOfMonth = calendar.get (Calendar.DAY_OF_MONTH) == daysInMonth;
        // 触发连续签到一个月的奖励
        if (isLastDayOfMonth && consecutiveDays == daysInMonth) {
//            BigDecimal monthScore = new BigDecimal (Optional.ofNullable (redisService.getVal (DictKey.user_sign_month_get.name ())).orElse ("0"));
//            if (monthScore.compareTo (BigDecimal.ZERO) == 0) {
//                SysDict sysDict = sysDictService.selectOne (DictKey.user_sign_month_get);
//                if(null == sysDict) {
//                    monthScore = new BigDecimal(0);
//                }else {
//                    monthScore = new BigDecimal (sysDict.getValue ());
//                }
//            }
            BigDecimal monthScore = new BigDecimal (Optional.ofNullable (sysDictService.selectOne(DictKey.user_sign_month_get)).map(SysDict::getValue).orElse("0"));

            if (isSign && !isHasGet) {
                // 更新余额
                balanceService.update(userId, BalanceType.SIGN, monthScore, null, "签到一月获取");
            }
        }


        List<UserSignDayDto> dayDtoList = new ArrayList<>();
        int i = 1;
        String memo;
        for (String day : weekDays) {
            UserSignDayDto signDto = new UserSignDayDto();

            switch (i) {
                case 1:
                    memo = "周一";
                    break;
                case 2:
                    memo = "周二";
                    break;
                case 3:
                    memo = "周三";
                    break;
                case 4:
                    memo = "周四";
                    break;
                case 5:
                    memo = "周五";
                    break;
                case 6:
                    memo = "周六";
                    break;
                case 7:
                    memo = "周日";
                    break;
                default:
                    memo = "";
            }

            System.out.println(day + ":" + todayDate);

            signDto.setIsToday(StringUtils.equals(day, todayDate) ? 1 : 0);
            signDto.setSignStatus(list.stream().anyMatch(v -> StringUtils.equals(DateUtils.formatDate(v.getSignDate(), "yyyy-MM-dd"), day)) ? 1 : 0);
            signDto.setMemo(memo);

            dayDtoList.add(signDto);
            i++;

        }

        dto.setList(dayDtoList);
        dto.setContent(sysDictService.selectOne(DictKey.user_sign_desc).getMemo());


        return FsResponseGen.successData(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse recordSignForAll(Long userId, boolean isSign) {

        UserSignDto dto = new UserSignDto();

        BigDecimal score = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_get)).map(SysDict::getValue).orElse("2"));

        BigDecimal scoreJifen = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_jifen_get)).map(SysDict::getValue).orElse("5"));


        Calendar calendar = Calendar.getInstance();
        String todayDate = DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd");

        // 查询用户今日是否已签到
        Example exampleOne = new Example(UserSign.class);
        exampleOne.createCriteria().andEqualTo("signDate", todayDate).andEqualTo("userId", userId);
        UserSign userSign = userSignMapper.selectOneByExample(exampleOne);

        if (null != userSign) {
            dto.setSignState(UserSignDto.SIGN_STATE_REPEAT);
        }
        else {
            dto.setSignState(UserSignDto.SIGN_STATE_SUCCESS);
        }


        boolean isLastDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) == 1;
        List<String> weekDays = new ArrayList<>();

        boolean isHasGet = false;
        if (isSign) {


            Example ex = new Example(UserSign.class);
            ex.createCriteria().andEqualTo("userId", userId).andEqualTo("signDate", todayDate);
            if (Objects.isNull(userSignMapper.selectOneByExample(ex))) {
                //获取每天签到的值
                UserSign sign = new UserSign();
                sign.setSignDate(new Date());
                sign.setScore(score);
                sign.setUserId(userId);
                sign.setCtime(new Date());
                userSignMapper.insertUseGeneratedKeys(sign);

                //添加入账记录
                balanceService.update(userId, BalanceType.SIGN, score, sign.getId().longValue(), "签到获取");
                //添加获取积分
                updateIntegralDetail(IntegralType.SIGN, sign.getId().toString(), scoreJifen.intValue(), userId);
            } else {
                isHasGet = true;
            }


        }


        //获取一周签到情况
        //重置日期为这周的第一天
        int d = calendar.get(Calendar.DAY_OF_WEEK);
        calendar.add(Calendar.DAY_OF_YEAR, d == 1 ? -6 : (2 - d));

        weekDays.add(DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd"));
        for (int i = 1; i < 7; i++) {
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            weekDays.add(DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd"));
        }

        //查询
        Example example = new Example(UserSign.class);
        example.createCriteria().andIn("signDate", weekDays).andEqualTo("userId", userId);

        List<UserSign> list = userSignMapper.selectByExample(example);

        //判断是否符合一周奖励
        //当前是否一周的最后一天
        //判断是否七天都签到
        BigDecimal weekScore = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_continue_get)).map(SysDict::getValue).orElse("0"));


        BigDecimal weekScoreJifen = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_continue_jifen_get)).map(SysDict::getValue).orElse("0"));

        // 满7天签到
        if (isLastDayOfWeek && list.size() == 7 && isSign && !isHasGet) {
            // 更新余额
            balanceService.update(userId, BalanceType.SIGN, weekScore, null, "签到一周获取");
            // 更新积分
            updateIntegralDetail(IntegralType.SIGN, null, weekScoreJifen.intValue(), userId);
        }


        // 查询用户近一个月的签到情况
        List<UserSign> listMonth = userSignMapper.selectUserSignMonth(userId);
        // 计算连续签到的天数
        int consecutiveDays = calculateConsecutiveDays(listMonth);
        // 获取当前月份的天数
//        int daysInMonth = calendar.getActualMaximum (Calendar.DAY_OF_MONTH);
        int daysInMonth = 30;        // 判断是否是当月的最后一天
        boolean isLastDayOfMonth = calendar.get (Calendar.DAY_OF_MONTH) == daysInMonth;
        // 触发连续签到一个月的奖励
        if (isLastDayOfMonth && consecutiveDays == daysInMonth) {
//            BigDecimal monthScore = new BigDecimal (Optional.ofNullable (redisService.getVal (DictKey.user_sign_month_get.name ())).orElse ("0"));
//            if (monthScore.compareTo (BigDecimal.ZERO) == 0) {
//                SysDict sysDict = sysDictService.selectOne (DictKey.user_sign_month_get);
//                if(null == sysDict) {
//                    monthScore = new BigDecimal(0);
//                }else {
//                    monthScore = new BigDecimal (sysDict.getValue ());
//                }
//            }
            BigDecimal monthScore = new BigDecimal (Optional.ofNullable (sysDictService.selectOne(DictKey.user_sign_month_get)).map(SysDict::getValue).orElse("0"));

            if (isSign && !isHasGet) {
                // 更新余额
                balanceService.update(userId, BalanceType.SIGN, monthScore, null, "签到一月获取");
                // 更新积分
                updateIntegralDetail(IntegralType.SIGN, userId + ": 连续签到一个月", monthScore.intValue(), userId);
            }
        }


        List<UserSignDayDto> dayDtoList = new ArrayList<>();
        int i = 1;
        String memo;
        for (String day : weekDays) {
            UserSignDayDto signDto = new UserSignDayDto();

            switch (i) {
                case 1:
                    memo = "周一";
                    break;
                case 2:
                    memo = "周二";
                    break;
                case 3:
                    memo = "周三";
                    break;
                case 4:
                    memo = "周四";
                    break;
                case 5:
                    memo = "周五";
                    break;
                case 6:
                    memo = "周六";
                    break;
                case 7:
                    memo = "周日";
                    break;
                default:
                    memo = "";
            }

            System.out.println(day + ":" + todayDate);

            signDto.setIsToday(StringUtils.equals(day, todayDate) ? 1 : 0);
            signDto.setSignStatus(list.stream().anyMatch(v -> StringUtils.equals(DateUtils.formatDate(v.getSignDate(), "yyyy-MM-dd"), day)) ? 1 : 0);
            signDto.setMemo(memo);

            dayDtoList.add(signDto);
            i++;

        }

        dto.setList(dayDtoList);
        dto.setContent(sysDictService.selectOne(DictKey.user_sign_desc).getMemo());


        return FsResponseGen.successData(dto);
    }


    /**
     * 签到接口-获取积分
     * @param userId
     * @param isSign
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse recordSignForIntegral(Long userId, boolean isSign) {

        UserSignDto dto = new UserSignDto();
        try {
            Calendar calendar = Calendar.getInstance();
            String todayDate = DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd");


            // 查询用户今日是否已签到
            Example exampleOne = new Example(UserSign.class);
            exampleOne.createCriteria().andEqualTo("signDate", todayDate).andEqualTo("userId", userId);
            UserSign userSign = userSignMapper.selectOneByExample(exampleOne);

            if (null != userSign) {
                dto.setSignState(UserSignDto.SIGN_STATE_REPEAT);
            }
            else {
                dto.setSignState(UserSignDto.SIGN_STATE_SUCCESS);
            }

//            BigDecimal score = new BigDecimal(Optional.ofNullable(redisService.getVal(DictKey.user_sign_get.name())).orElse("0"));
//            if (score.compareTo(BigDecimal.ZERO) == 0) {
//                SysDict sysDict = sysDictService.selectOne(DictKey.user_sign_get);
//                Contracts.assertNotNull(sysDict, YiChatMsgCode.USER_SIGN_FAIL.msg());
//                score = new BigDecimal(sysDict.getValue());
//            }
            BigDecimal score = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_get)).map(SysDict::getValue).orElse("2"));



            boolean isLastDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) == 1;
            List<String> weekDays = new ArrayList<>();

            boolean isHasGet = false;
            if (isSign) {


                Example ex = new Example(UserSign.class);
                ex.createCriteria().andEqualTo("userId", userId).andEqualTo("signDate", todayDate);
                if (Objects.isNull(userSignMapper.selectOneByExample(ex))) {
                    //获取每天签到的值
                    UserSign sign = new UserSign();
                    sign.setSignDate(new Date());
                    sign.setScore(score);
                    sign.setUserId(userId);
                    sign.setCtime(new Date());
                    userSignMapper.insertUseGeneratedKeys(sign);

                    //添加获取积分
                    updateIntegralDetail(IntegralType.SIGN, null, score.intValue(), userId);
                } else {
                    isHasGet = true;
                }


            }


            //获取一周签到情况
            //重置日期为这周的第一天
            int d = calendar.get(Calendar.DAY_OF_WEEK);
            calendar.add(Calendar.DAY_OF_YEAR, d == 1 ? -6 : (2 - d));

            weekDays.add(DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd"));
            for (int i = 1; i < 7; i++) {
                calendar.add(Calendar.DAY_OF_YEAR, 1);
                weekDays.add(DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd"));
            }

            //查询
            Example example = new Example(UserSign.class);
            example.createCriteria().andIn("signDate", weekDays).andEqualTo("userId", userId);

            List<UserSign> list = userSignMapper.selectByExample(example);

            //判断是否符合一周奖励
            //当前是否一周的最后一天
            //判断是否七天都签到
//            BigDecimal weekScore = new BigDecimal(Optional.ofNullable(redisService.getVal(DictKey.user_sign_continue_get.name())).orElse("0"));
//            if (weekScore.compareTo(BigDecimal.ZERO) == 0) {
//                SysDict sysDict = sysDictService.selectOne(DictKey.user_sign_continue_get);
//                Contracts.assertNotNull(sysDict, YiChatMsgCode.USER_SIGN_FAIL.msg());
//                weekScore = new BigDecimal(sysDict.getValue());
//            }
            BigDecimal weekScore = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_continue_get)).map(SysDict::getValue).orElse("0"));


            if (isLastDayOfWeek && list.size() == 7 && isSign && !isHasGet) {

                updateIntegralDetail(IntegralType.SIGN, null, weekScore.intValue(), userId);
            }

            // 查询用户近一个月的签到情况
            List<UserSign> listMonth = userSignMapper.selectUserSignMonth(userId);
            // 计算连续签到的天数
            int consecutiveDays = calculateConsecutiveDays(listMonth);
            // 获取当前月份的天数
//        int daysInMonth = calendar.getActualMaximum (Calendar.DAY_OF_MONTH);
            int daysInMonth = 30;            // 判断是否是当月的最后一天
            boolean isLastDayOfMonth = calendar.get (Calendar.DAY_OF_MONTH) == daysInMonth;
            // 触发连续签到一个月的奖励
            if (isLastDayOfMonth && consecutiveDays == daysInMonth) {
//                BigDecimal monthScore = new BigDecimal (Optional.ofNullable (redisService.getVal (DictKey.user_sign_month_get.name ())).orElse ("0"));
//                if (monthScore.compareTo (BigDecimal.ZERO) == 0) {
//                    SysDict sysDict = sysDictService.selectOne (DictKey.user_sign_month_get);
//                    if(null == sysDict) {
//                        monthScore = new BigDecimal(0);
//                    }else {
//                        monthScore = new BigDecimal (sysDict.getValue ());
//                    }
//                }
                BigDecimal monthScore = new BigDecimal (Optional.ofNullable (sysDictService.selectOne(DictKey.user_sign_month_get)).map(SysDict::getValue).orElse("0"));

                if (isSign && !isHasGet) {
                    updateIntegralDetail(IntegralType.SIGN, userId + ": 连续签到一个月", monthScore.intValue(), userId);
                }
            }


            List<UserSignDayDto> dayDtoList = new ArrayList<>();
            int i = 1;
            String memo;
            for (String day : weekDays) {
                UserSignDayDto signDto = new UserSignDayDto();

                switch (i) {
                    case 1:
                        memo = "周一";
                        break;
                    case 2:
                        memo = "周二";
                        break;
                    case 3:
                        memo = "周三";
                        break;
                    case 4:
                        memo = "周四";
                        break;
                    case 5:
                        memo = "周五";
                        break;
                    case 6:
                        memo = "周六";
                        break;
                    case 7:
                        memo = "周日";
                        break;
                    default:
                        memo = "";
                }

                System.out.println(day + ":" + todayDate);

                signDto.setIsToday(StringUtils.equals(day, todayDate) ? 1 : 0);
                signDto.setSignStatus(list.stream().anyMatch(v -> StringUtils.equals(DateUtils.formatDate(v.getSignDate(), "yyyy-MM-dd"), day)) ? 1 : 0);
                signDto.setMemo(memo);

                dayDtoList.add(signDto);
                i++;

            }

            dto.setList(dayDtoList);
            dto.setContent(sysDictService.selectOne(DictKey.user_sign_desc).getMemo());
        }catch (Exception e) {
            log.error("签到失败！", e.getMessage());
            dto.setSignState(UserSignDto.SIGN_STATE_FAIL);
            return FsResponseGen.successData(dto);
        }

        return FsResponseGen.successData(dto);
    }

    /**
     * 更新用户积分
     * @param type
     * @param referId
     * @param score
     * @param userId
     */
    private void updateIntegralDetail(IntegralType type, String referId, Integer score, Long userId) {

        //增加用户积分记录
        UserIntegralDetail detail = new UserIntegralDetail();
        detail.setIntegral(score);
        detail.setReferType(type.getVal());
        detail.setMemo(type.getDesc());
        detail.setUserId(userId);
        detail.setReferId(referId);
        userIntegralDetailMapper.insertSelective(detail);

        //更新user表的积分值
        userMapper.addIntegral(score, userId);

    }


    @Override
    public void updatePassword(Long userId, String password) {
        User user = new User();
        user.setId(userId);
        user.setPassword(MD5Util.shaEncode(password));
        userMapper.updateByPrimaryKeySelective(user);
    }


    /**
     * 计算连续签到的天数
     */
    private int newCalculateConsecutiveDays (List<UserSign> signList, boolean isSign) {
        int consecutiveDays = 0;
        int currentStreak = 0;
        Date currentDate = new Date();

        for (UserSign sign : signList) {
            // 计算当前记录距离今天的天数
            long daysDiff = daysBetween(sign.getSignDate(), currentDate);

            if (isSign) {
                if (daysDiff == currentStreak) {
                    // 连续签到
                    currentStreak++;
                } else {
                    // 重置连续签到计数
                    currentStreak = 0;
                }

                if (currentStreak > consecutiveDays) {
                    consecutiveDays = currentStreak;
                }
            }else {
                if (daysDiff == currentStreak || (daysDiff == currentStreak + 1)) {
                    // 连续签到
                    currentStreak++;
                } else {
                    // 重置连续签到计数
                    currentStreak = 0;
                }

                if (currentStreak > consecutiveDays) {
                    consecutiveDays = currentStreak;
                }
            }
        }

        return consecutiveDays;
    }

    /**
     * 计算连续签到的天数
     */
    private int calculateConsecutiveDays (List<UserSign> signList) {
        int consecutiveDays = 0;
        int currentStreak = 0;
        Date currentDate = new Date();

        for (UserSign sign : signList) {
            // 计算当前记录距离今天的天数
            long daysDiff = daysBetween(sign.getSignDate(), currentDate);

            if (daysDiff == currentStreak) {
                // 连续签到
                currentStreak++;
            } else {
                // 重置连续签到计数
                currentStreak = 0;
            }

            if (currentStreak > consecutiveDays) {
                consecutiveDays = currentStreak;
            }
        }

        return consecutiveDays;
    }

    private long daysBetween (Date date1, Date date2) {
        long diffInMillies = date2.getTime () - date1.getTime ();
        return TimeUnit.DAYS.convert (diffInMillies, TimeUnit.MILLISECONDS);
    }

    @Async
    @Override
    public void saveIp(String ip, Long userId) {
        if (StringUtils.isBlank(ip)) {
            return;
        }
        List<UserIp> ipList = getUserIps(userId);

        if (GeneralUtils.isNotNullOrEmpty(ipList)) {
            for (int i = 0; i < ipList.size(); i++) {
                //只保存最近5条登陆IP记录
                if (i > 4 || StringUtils.equals(ipList.get(i).getIp(), ip)) {
                    userIpMapper.deleteByPrimaryKey(ipList.get(i).getId());
                }
            }
        }

        //插入当前数据
        UserIp inser = new UserIp();
        inser.setIp(ip);
        inser.setUserId(userId);
        userIpMapper.insertSelective(inser);

    }

    @Override
    public List<UserIp> getUserIps(Long userId) {
        //查询记录的数据
        Example select = new Example(UserIp.class);
        select.createCriteria().andEqualTo("userId", userId);
        select.setOrderByClause(" id desc");
        return userIpMapper.selectByExample(select);
    }

//    @Override
//    public boolean saveValid(Long userId, String realName, String idNumber, String imgs) {
//
//        //实名认证
//        if (!validUserIdNumber(realName, idNumber)) {
//            return false;
//        }
//
//        User user = new User();
//        user.setId(userId);
//        user.setRealName(realName);
//        user.setIdNumber(idNumber);
//        user.setRealStatus(-1);
//        user.setIdImgs(imgs);
//
//        userMapper.updateByPrimaryKeySelective(user);
//        return true;
//    }


    public boolean validUserIdNumber(String name, String idCard) {
        String host = "https://edis2s.market.alicloudapi.com";
        String path = "/edis_ctid_id_name";
        String method = "POST";
        String appcode = "550fa906ed5d4057988dc478be15b1d2";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE 550fa906ed5d4057988dc478be15b1d2");
        String str = UUID.randomUUID().toString();
        System.out.println(str);
        headers.put("x-ca-nonce", str);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();


        boolean flag = false;


        OkHttpClient client = new OkHttpClient();

        String result = null;
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=utf-8"), "name=" + name + "&idCard=" + idCard);
        Request.Builder builder = new Request.Builder();
        if (Objects.nonNull(headers)) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        Request request = builder.url(host + path).post(requestBody).build();
        try {
            Response response = client.newCall(request).execute();
            result = response.body().string();
            if (JSON.parseObject(result).getString("code").equals("0000")) {
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


        return flag;

    }

    @Override
    public User selectByCode(String recommendCode) {
        Example example = new Example(User.class);
        example.createCriteria().andEqualTo(FsConst.SqlColumn.STATUS, FsConst.Status.EFFECT).andEqualTo("ucode", recommendCode);
        return userMapper.selectOneByExample(example);

    }

    @Override
    public FsResponse selectRecommendList(FsPage page, Long userId) {

        User user = selectById(userId);

        Example example = new Example(User.class);
        example.createCriteria().andEqualTo("recommendCode", user.getUcode());
        example.setOrderByClause(" id desc");
        //PageHelper.startPage(page.getPageNo(), page.getPageSize());
       // int integral = NumberUtils.toInt(sysDictService.selectOne(DictKey.integral_invite).getValue());

        return DtoChangeUtils.getPageList(userMapper.selectByExample(example), copy -> {
            UserSearchDto dto = new UserSearchDto();
           // dto.setIntegral(integral);
            dto.setUserId(copy.getId());
            dto.setAvatar(copy.getAvatar());
            dto.setNick(copy.getNick());
            //dto.setAppId(copy.getAppid());
            //0好友关系 1否
            //dto.setFriendStatus(friendService.isFriend(userId, copy.getId()) ? 0 : 1);
            //dto.setTimeDesc(DateUtils.formatDate(copy.getRecommendTime()));
            return dto;
        });
    }

    @Override
    public List<UserInviteSearchDto> selectRecommendList2(FsPage page, Long userId) {
        return userInviteMapper.selectUserInviteList(userId);
    }


    @Override
    public boolean validStatus(Long userId) {
        //        User user = selectById(userId);
        //        return StringUtils.isNotBlank(user.getRealName()) && StringUtils.isNotBlank(user.getIdNumber());

//        boolean old = validOldUser(null, 1, null, userId);
//        if (old) {
//            return realValidStatus(userId);
//        }
//        return true;
        return realValidStatus(userId);
    }

    @Override
    public boolean realValidStatus(Long userId) {
        User user = selectById(userId);
        return StringUtils.isNotBlank(user.getRealName()) && StringUtils.isNotBlank(user.getIdNumber()) ;
    }

    @Override
    public boolean validStatus2(String currentIp, Long userId) {
        //苹果审核员的特殊处理
        if (Objects.equals(userId, "15001580")) {
            return realValidStatus(userId);
        }
        //        //获取通过此ip登录的用户个数
        //        if (StringUtils.isNotEmpty(currentIp)) {
        //            Long ipCount = userIpMapper.countSameIp(currentIp);
        //
        //            if (Objects.nonNull(ipCount) && ipCount > 2) {
        //                return realValidStatus(userId);
        //            }
        //        }

        return validStatus(userId);
    }

    @Override
    public boolean validOldUser(Integer viewCount, Integer withdrawCount, Integer receiveCount, Long userId) {
//        if (Objects.isNull(userId)) {
//            return false;
//        }
//
//        if (Objects.nonNull(viewCount)) {
//            Example viewEx = new Example(PacketSaleView.class);
//            viewEx.createCriteria().andEqualTo("userId", userId);
//            int viewC = packetSaleViewMapper.selectCountByExample(viewEx);
//
//            if (viewC > viewCount) {
//                return true;
//            }
//        }
//
//        if (Objects.nonNull(withdrawCount)) {
//            Example withdrawEx = new Example(UserWithdraw.class);
//            withdrawEx.createCriteria().andEqualTo("userId", userId).andEqualTo("status", 1);
//            int withdrawC = userWithdrawMapper.selectCountByExample(withdrawEx);
//
//            if (withdrawC > withdrawCount) {
//                return true;
//            }
//        }
//
//        if (Objects.nonNull(receiveCount)) {
//            Example receiveEx = new Example(PacketSaleReceive.class);
//            receiveEx.createCriteria().andEqualTo("userId", userId).andEqualTo("status", 1);
//            int receiveC = packetSaleReceiveMapper.selectCountByExample(receiveEx);
//
//            if (receiveC > receiveCount) {
//                return true;
//            }
//        }
//
//        return false;
        return realValidStatus(userId);
    }

    @Override
    public boolean updatePasswordToIm(User user, String password) {

        // 拼接Im工程的更新密码的路径
        String path = imUri + "user/reset_password_back";
        JSONObject jsonObject = new JSONObject();
        try {
            String encryptPassword = AesUtil.encrypt(password, "A286D372M63HFYUS");
            jsonObject.put("password", encryptPassword);
            jsonObject.put("userId", user.getId());

            String resp = OKHttpUtil.httpPostJson(path, jsonObject.toJSONString(), commonHeader());
            FsResponse response = JSONObject.parseObject(resp, FsResponse.class);
            String code = response.getCode();
            return "200".equals(code);
        } catch (Exception e) {
            log.error("用户更新密码错误: userId: ", user.getId());
            throw new ServiceException(e.getMessage());
        }
    }

    @Override
    public int updateUser(User updateUser) {
        return userMapper.updateByPrimaryKeySelective(updateUser);
    }

    @Override
    public WxUser selectWxUserList(Long id) {
        return wxUserMapper.selectWxUserList(id);
    }

    @Override
    public String selectNickNameById(Long userId) {
        return userMapper.selectNickNameById(userId);
    }

    @Override
    public void insertUserIntegralDetail(UserIntegralDetail detail) {
        userIntegralDetailMapper.insertSelective(detail);
    }

    @Override
    public void addIntegral(Integer score, Long userId) {
        userMapper.addIntegral(score, userId);;
    }

    @Override
    public Integer queryUserIntegralToday(Long decodeUserId) {
        return userIntegralDetailMapper.queryUserIntegralToday(decodeUserId);
    }

    @Override
    public Integer queryUserIntegralTimeDifference(Long decodeUserId) {
        return userIntegralDetailMapper.queryUserIntegralTimeDifference(decodeUserId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse activateMembership(Long userId, String password, BigDecimal money) {

        User user = userMapper.queryUserByParam("", userId);
        if (null == user) {
            return FsResponseGen.failMsg("用户不存在，userId: " + userId);
        }

        UserBalance balance = balanceService.selectByUserId(userId);
        Contracts.assertTrue(balance.getIncomeBalance().compareTo(money) >= 0, YiChatMsgCode.PACKET_CREATE_NO_ENOUGH_BALANCE.msg());

        // 更新用户余额
        balanceService.update(userId, BalanceType.USER_OPENS_MEMBERSHIP, money, userId, BalanceType.USER_OPENS_MEMBERSHIP.getDesc());

        User userUpdate = new User();
        userUpdate.setId(userId);
        userUpdate.setLevel(User.LEVEL_MEMBER);
        // 更新用户级别
        userMapper.updateByPrimaryKeySelective(userUpdate);

        return FsResponseGen.successData(userMapper.queryUserByParam("", userId));
    }

    @Override
    public UserTasksInfoDto getUserTasksInfo(Long userId) {

        UserTasksInfoDto infoDto = new UserTasksInfoDto();

        // 注册部分
        // 判断用户是否已领取注册积分
        Example exampleRegister = new Example(UserIntegralDetail.class);
        Example.Criteria criteriaRegister = exampleRegister.createCriteria();
        criteriaRegister.andEqualTo("userId", userId).andEqualTo("referType", IntegralType.REGISTER_CONSUME.getVal());
        List<UserIntegralDetail> registerList = userIntegralDetailMapper.selectByExample(exampleRegister);

        UserIntegralDetail detailRegister = null;
        if (null != registerList && registerList.size() > 0) {
            detailRegister = registerList.get(0);
        }

        SysDict sysDictRegister = sysDictService.selectOne(DictKey.user_register_give_integral);
        Integer integralRegister = 0;
        if (null == sysDictRegister) {
            integralRegister = 0;
        }else {
            integralRegister = Integer.valueOf(sysDictRegister.getValue());
        }

        UserTasksInfoDto.Register register = infoDto.new Register();
        register.setIntegral(integralRegister);
        register.setType(User.REGISTER_TYPE);
        register.setStatus(null == detailRegister ? UserTasksInfoDto.status_1 : UserTasksInfoDto.status_2);

        // 实名认证部分

        UserTasksInfoDto.RealName realName = infoDto.new RealName();

        Integer integralRealName = 0;
        SysDict sysDictRealName = sysDictService.selectOne(DictKey.user_real_name_give_integral);
        if (null == sysDictRealName) {
            integralRealName = 0;
        }else {
            integralRealName = Integer.valueOf(sysDictRealName.getValue());
        }

        realName.setIntegral(integralRealName);
        realName.setType(User.REAL_NAME_TYPE);

        // 判断是否已完成实名认证
        boolean realValidStatus = realValidStatus(userId);
        if (!realValidStatus) {
            realName.setStatus(UserTasksInfoDto.status_0);
        }
        else {
            Example exampleRealName = new Example(UserIntegralDetail.class);
            Example.Criteria criteriaRealName = exampleRealName.createCriteria();
            criteriaRealName.andEqualTo("userId", userId).andEqualTo("referType", IntegralType.REAL_NAME_CONSUME.getVal());
            List<UserIntegralDetail> realNameList = userIntegralDetailMapper.selectByExample(exampleRealName);

            UserIntegralDetail detailRealName = null;
            if (null != realNameList && realNameList.size() > 0) {
                detailRealName = realNameList.get(0);
            }

            if (null == detailRealName) {
                realName.setStatus(UserTasksInfoDto.status_1);
            }
            else {
                realName.setStatus(UserTasksInfoDto.status_2);
            }
        }

        // 绑卡部分

        UserTasksInfoDto.BindCard bindCard = infoDto.new BindCard();

        Integer integralCard = 0;
        SysDict sysDictBindCard = sysDictService.selectOne(DictKey.user_bind_card_give_integral);
        if (null == sysDictBindCard) {
            integralCard = 0;
        }else {
            integralCard = Integer.valueOf(sysDictBindCard.getValue());
        }
        bindCard.setIntegral(integralCard);
        bindCard.setType(User.BIND_CARD_TYPE);
        // 判断用户是否绑卡
        boolean isBind = false;
      //  User user = userMapper.queryUserByParam("", userId);

            Example exampleUserBank=new Example(UserBank.class);
            exampleUserBank.createCriteria().andEqualTo("userId", userId);
            int count = userBankMapper.selectCountByExample(exampleUserBank);
            if(count >= 1){
                isBind = true;
            }


        if (!isBind) {
            bindCard.setStatus(UserTasksInfoDto.status_0);
        }
        else {
            Example exampleCard = new Example(UserIntegralDetail.class);
            Example.Criteria criteriaCard = exampleCard.createCriteria();
            criteriaCard.andEqualTo("userId", userId).andEqualTo("referType", IntegralType.BIND_CARD_CONSUME.getVal());
            List<UserIntegralDetail> cardList = userIntegralDetailMapper.selectByExample(exampleCard);

            UserIntegralDetail detailCard = null;
            if (null != cardList && cardList.size() > 0) {
                detailCard = cardList.get(0);
            }

            if (null == detailCard) {
                bindCard.setStatus(UserTasksInfoDto.status_1);
            }
            else {
                bindCard.setStatus(UserTasksInfoDto.status_2);
            }
        }

        infoDto.setRegister(register);
        infoDto.setRealName(realName);
        infoDto.setBindCard(bindCard);
        return infoDto;
    }

    @Override
    public List<UserLowerLevelDto> queryLowerLevel(Long userId) {
        User user = userMapper.queryUserByParam("", userId);
        if (null == user) {
            return new ArrayList<>();
        }

        String ucode = user.getUcode();
        if (StringUtils.isBlank(ucode)) {
            return new ArrayList<>();
        }

        return userMapper.queryLowerLevelAndCount(ucode);
    }

    @Override
    public List<MemberLevelDto> getUserLevel() {
        List<MemberLevelDto> userLevelList = memberLevelMapper.getUserLevel();
        for (MemberLevelDto dto : userLevelList) {
            Long levelId = dto.getId();
            List<MemberLevelPrivilege> privilegeList = memberLevelPrivilegeMapper.queryListByLevelId(levelId);
            dto.setPrivilegeList(privilegeList);
        }

        return userLevelList;
    }

    @Override
    public FsResponse activateMembershipForType(Long userId, String password, BigDecimal money, Integer type) {
        User user = userMapper.queryUserByParam("", userId);
        if (null == user) {
            return FsResponseGen.failMsg("用户不存在，userId: " + userId);
        }

        UserBalance balance = balanceService.selectByUserId(userId);
        Contracts.assertTrue(balance.getIncomeBalance().compareTo(money) >= 0, YiChatMsgCode.PACKET_CREATE_NO_ENOUGH_BALANCE.msg());

        // 更新用户余额
        if (User.LEVEL_MEMBER.equals(type)) {
            balanceService.update(userId, BalanceType.USER_OPENS_MEMBERSHIP, money, userId, BalanceType.USER_OPENS_MEMBERSHIP.getDesc());
        }
        if (User.LEVEL_MEMBER_INTERMEDIATE.equals(type)) {
            balanceService.update(userId, BalanceType.USER_OPENS_MEMBERSHIP_INTERMEDIATE, money, userId, BalanceType.USER_OPENS_MEMBERSHIP_INTERMEDIATE.getDesc());
        }

        if (User.LEVEL_SUPREME_MEMBER.equals(type)) {
            balanceService.update(userId, BalanceType.USER_OPENS_MEMBERSHIP_SUPREME, money, userId, BalanceType.USER_OPENS_MEMBERSHIP_SUPREME.getDesc());
        }

        if (User.LEVEL_ULTIMATE_MEMBER.equals(type)) {
            balanceService.update(userId, BalanceType.USER_OPENS_MEMBERSHIP_ULTIMATE, money, userId, BalanceType.USER_OPENS_MEMBERSHIP_ULTIMATE.getDesc());
        }

        if (User.LEVEL_STARLIGHT_MEMBER.equals(type)) {
            balanceService.update(userId, BalanceType.USER_OPENS_MEMBERSHIP_ULTIMATE, money, userId, BalanceType.USER_OPENS_MEMBERSHIP_ULTIMATE.getDesc());
        }

        User userUpdate = new User();
        userUpdate.setId(userId);
        userUpdate.setLevel(type);
        // 更新用户级别
        userMapper.updateByPrimaryKeySelective(userUpdate);

        return FsResponseGen.successData(userMapper.queryUserByParam("", userId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse continuousSign(Long userId, boolean isSign, String type) {
        synchronized (SysInternPool.INSTANCE.internUid(userId)) {
            UserSignContinuousDto dto = new UserSignContinuousDto();
            try {
                Calendar calendar = Calendar.getInstance();
                String todayDate = DateUtils.formatDate(calendar.getTime(), "yyyy-MM-dd");

                // 查询用户今日是否已签到
                Example exampleOne = new Example(UserSign.class);
                exampleOne.createCriteria().andEqualTo("signDate", todayDate).andEqualTo("userId", userId);
                UserSign userSign = userSignMapper.selectOneByExample(exampleOne);

                // 今天是否签到
                boolean todaySign = null != userSign;
                if (isSign) {
                    if (todaySign) {
                        dto.setSignState(UserSignDto.SIGN_STATE_REPEAT);
                    }
                    else {
                        dto.setSignState(UserSignDto.SIGN_STATE_SUCCESS);
                    }
                }else {
                    if (todaySign) {
                        dto.setSignState(UserSignDto.SIGN_STATE_SUCCESS);
                    }
                    else {
                        dto.setSignState(UserSignDto.SIGN_STATE_No);
                    }
                }

                BigDecimal score = new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_get)).map(SysDict::getValue).orElse("2"));
                boolean isHasGet = false;
                if (isSign) {
                    Example ex = new Example(UserSign.class);
                    ex.createCriteria().andEqualTo("userId", userId).andEqualTo("signDate", todayDate);
                    if (Objects.isNull(userSignMapper.selectOneByExample(ex))) {
                        //获取每天签到的值
                        UserSign sign = new UserSign();
                        sign.setSignDate(new Date());
                        sign.setScore(score);
                        sign.setUserId(userId);
                        sign.setCtime(new Date());
                        userSignMapper.insertUseGeneratedKeys(sign);

                        // 都赠送
                        if (type.equals("0")) {
                            //添加入账记录
                            balanceService.update(userId, BalanceType.SIGN, score, sign.getId().longValue(), "签到获取");
                            BigDecimal jifenscore= new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_jifen_get)).map(SysDict::getValue).orElse("5"));
                            //添加获取积分
                            updateIntegralDetail(IntegralType.SIGN, sign.getId().toString(), jifenscore.intValue(), userId);
                        }
                        // 赠送余额
                        else if (type.equals("1")) {
                            //添加入账记录
                            balanceService.update(userId, BalanceType.SIGN, score, sign.getId().longValue(), "签到获取");
                        }
                        // 赠送积分
                        else {
                            BigDecimal jifenscore= new BigDecimal(Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_jifen_get)).map(SysDict::getValue).orElse("5"));
                            //添加获取积分
                            updateIntegralDetail(IntegralType.SIGN, sign.getId().toString(), jifenscore.intValue(), userId);
                        }
                    } else {
                        isHasGet = true;
                    }

                }

                // 查询用户近一个月的签到情况
                List<UserSign> signList = userSignMapper.selectContinuousSignByUserId(userId);
                // 查询用户今日是否已签到
                Example exampleSign = new Example(UserSign.class);
                exampleSign.createCriteria().andEqualTo("signDate", todayDate).andEqualTo("userId", userId);
                UserSign userSigns = userSignMapper.selectOneByExample(exampleSign);

                // 今天是否签到
                boolean todaySigns = null != userSigns;
                // 计算连续签到的天数
                int consecutiveDays = newCalculateConsecutiveDays(signList, todaySigns);


                //判断是否符合一周奖励//当前是否一周的最后一天//判断是否七天都签到
                BigDecimal  weekScore = new BigDecimal(  Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_continue_get)).map(SysDict::getValue).orElse("0"));
                int consecutive7Days = calculateValue(consecutiveDays, 7);
                // 触发连续签到7的奖励
                if (consecutive7Days == 7 && isSign && !isHasGet) {
                    // 都赠送
                    if (type.equals("0")) {
                        // 更新余额
                        balanceService.update(userId, BalanceType.SIGN, weekScore, null, "连续签到7天获取");
                        BigDecimal jifenweekScore = new BigDecimal(  Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_continue_jifen_get)).map(SysDict::getValue).orElse("0"));

                        // 更新积分
                        updateIntegralDetail(IntegralType.SIGN, userId + ": 连续签到7天获取", jifenweekScore.intValue(), userId);
                    }
                    // 赠送余额
                    else if (type.equals("1")) {
                        // 更新余额
                        balanceService.update(userId, BalanceType.SIGN, weekScore, null, "连续签到7天获取");
                    }
                    // 赠送积分
                    else {
                        BigDecimal jifenweekScore= new BigDecimal(  Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_continue_jifen_get)).map(SysDict::getValue).orElse("0"));

                        // 更新积分
                        updateIntegralDetail(IntegralType.SIGN, userId + ": 连续签到7天获取", jifenweekScore.intValue(), userId);
                    }
                }


                int consecutive30Days = calculateValue(consecutiveDays, 30);
                // 获取当前月份的天数
                // 触发连续签到30的奖励
                if (consecutive30Days == 30) {
                    BigDecimal  monthScore= new BigDecimal(  Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_month_get)).map(SysDict::getValue).orElse("0"));
                    if (isSign && !isHasGet) {
                        // 都赠送
                        if (type.equals("0")) {
                            // 更新余额
                            balanceService.update(userId, BalanceType.SIGN, monthScore, null, "连续签到30天获取");
                            // 更新积分
                            BigDecimal jifenmonthScore= new BigDecimal(  Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_month_jifen_get)).map(SysDict::getValue).orElse("0"));

                            updateIntegralDetail(IntegralType.SIGN, userId + ": 连续签到30天获取", jifenmonthScore.intValue(), userId);
                        }
                        // 赠送余额
                        else if (type.equals("1")) {
                            // 更新余额
                            balanceService.update(userId, BalanceType.SIGN, monthScore, null, "连续签到30天获取");
                        }
                        // 赠送积分
                        else {
                            BigDecimal jifenmonthScore= new BigDecimal(  Optional.ofNullable(sysDictService.selectOne(DictKey.user_sign_month_jifen_get)).map(SysDict::getValue).orElse("0"));

                            // 更新积分
                            updateIntegralDetail(IntegralType.SIGN, userId + ": 连续签到30天", jifenmonthScore.intValue(), userId);
                        }
                    }
                }

                // 签到赠送浇水次数
                if (isSign && !isHasGet) {
                    if (!todaySign) {
                        plantTreeService.addTask(userId,"签到", UserPrintTreeTask.SIGN_TASK, 1);
                    }
                }

                // 计算连续签到的天数
                int consecutiveDay = newCalculateConsecutiveDays(signList, todaySigns);
                dto.setContinuousDays(consecutiveDay);
                dto.setSingleReward(score.intValue());
                dto.setContent(sysDictService.selectOne(DictKey.user_sign_desc).getMemo());
            }catch (Exception e) {
                log.error("签到失败！", e.getMessage());
                dto.setSignState(UserSignDto.SIGN_STATE_FAIL);
                return FsResponseGen.successData(dto);
            }

            return FsResponseGen.successData(dto);
        }
    }

    @Override
    public Integer queryUserActivateMembership(Long userId, Integer type) {

        Integer detailsType = BalanceType.USER_OPENS_MEMBERSHIP.getVal();
        if (User.LEVEL_MEMBER_INTERMEDIATE.equals(type)) {
            detailsType = BalanceType.USER_OPENS_MEMBERSHIP_INTERMEDIATE.getVal();
        }
        if (User.LEVEL_SUPREME_MEMBER.equals(type)) {
            detailsType = BalanceType.USER_OPENS_MEMBERSHIP_SUPREME.getVal();
        }
        if (User.LEVEL_ULTIMATE_MEMBER.equals(type)) {
            detailsType = BalanceType.USER_OPENS_MEMBERSHIP_ULTIMATE.getVal();
        }
        if (User.LEVEL_STARLIGHT_MEMBER.equals(type)) {
            detailsType = BalanceType.USER_OPENS_MEMBERSHIP_STARLIGHT.getVal();
        }
        Example example = new Example(UserBalanceDetail.class);
        example.createCriteria().andEqualTo("userId", userId).andEqualTo("type", detailsType);
        return userBalanceDetailMapper.selectCountByExample(example);
    }

    @Override
    public int queryInvitationsNumToday(String recommendCode) {
        return userMapper.queryInvitationsNumToday(recommendCode);
    }

    @Override
    public int queryUserByMobile(String mobile) {
        Example example = new Example(User.class);
        example.createCriteria().andEqualTo("mobile", mobile).andEqualTo("status", User.STATUS_0);
        return userMapper.selectCountByExample(example);
    }

    @Override
    public void expireRongYunUserToken(Long userId) {

        try {
            String encodeUserId = N3d.encode(userId);
            HttpPost httpPostCreate = rongCloudApplication.imConstructor("user/token/expire");
            List<NameValuePair> paramsCreate = new ArrayList<>();
            paramsCreate.add(new BasicNameValuePair("userId", encodeUserId));
            paramsCreate.add(new BasicNameValuePair("time", Long.toString(System.currentTimeMillis())));
            httpPostCreate.setEntity(new UrlEncodedFormEntity(paramsCreate, StandardCharsets.UTF_8));

            String responseCreate = rongCloudApplication.executeReq(httpPostCreate);
            // 解析响应数据
            JSONObject jsonObjectCreate = JSON.parseObject(responseCreate);
            String keepaliveCodeCreate = jsonObjectCreate.getString("code");

            if ("200".equals(keepaliveCodeCreate)) {
                log.info("作废融云Token成功：userId:" + userId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("作废融云Token失败！");
        }


    }

    // 计算连续签到天数
    public int calculateValue(int input, int day) {
        if (input <= day) {
            // 如果小于30，返回原值
            return input;
        } else {
            // 计算减去30的倍数后的值
            int remainder = input % day;
            return remainder;
        }
    }

    private Map<String, String> commonHeader() {
        Map<String, String> result = new HashMap<>();
        result.put("None-AES", "1");
        result.put("Content-Type", "application/json");
        result.put("Authorization", "Basic YWRtaW5AYXBwLmltOjEyMzQ1NkBhcHA=");
        return result;
    }

    @Override
    public List<User> queryAllFreezeUser() {
        Example ex = new Example(User.class);
        ex.createCriteria().andEqualTo("status", User.STATUS_1);
        return userMapper.selectByExample(ex);
    }


}
